package com.hxzrz111.java8.lambda;

import java.util.*;

/**
 * 你可能会有疑问，Java8 中不是允许通过 default 关键字来为接口添加默认方法吗？
 * 那它算不算抽象方法呢？答案是：不算。因此，你可以毫无顾忌的添加默认方法，
 * 它并不违反函数式接口的定义。
 *
 * 总结：
 * 只要接口中仅仅包含一个抽象方法，我们就可以将其改写为 Lambda 表达式。为了保证
 * 一个接口明确的被定义为一个函数式接口（Functional Interface），我们需要为改接口添加注解：
 * @FunctionalInterface 。这样，一旦你添加了第二个抽象方法，编译器会立刻抛出错误提示。
 */
public class Main {

    public static void main(String[] args) {

        Main main = new Main();

        // 类型声明
        MathOperation addition = (int a, int b) -> a + b;

        // 不用类型声明
        MathOperation subtraction = (a, b) -> a - b;

        // 大括号及返回语句
        MathOperation multiplication = (int a, int b) -> { return a * b; };

        // 没有大括号及返回语句
        MathOperation division = (int a, int b) -> a / b;

        System.out.println("10 + 5 = " + main.operate(10, 5, addition));
        System.out.println("10 - 5 = " + main.operate(10, 5, subtraction));
        System.out.println("10 * 5 = " + main.operate(10, 5, multiplication));
        System.out.println("10 / 5 = " + main.operate(10, 5, division));

        // 不用括号
        GreetingService greetingService = message ->
                System.out.println("hello" + message);

        // 用括号
        GreetingService greetingServicel = (message) ->
                System.out.println("hello" + message);

        greetingService.sayMessage("google");
        greetingServicel.sayMessage("big");

    }

    /**
     * 函数式接口
     *
     * 只有函数式接口才能缩写成Lambda表达式
     *
     * 什么是函数式接口呢？
     *
     * 所谓的函数式接口 (Functional Interface) 就是只包含一个抽象方法的声明。
     * 针对该接口类型的所有Lambda表达式都会与这个抽象方法匹配。
     */
    @FunctionalInterface
    interface MathOperation {
        int operation(int a, int b);
    }

    @FunctionalInterface
    interface  GreetingService {
        void sayMessage(String message);
    }

    private int operate(int a, int b, MathOperation mathOperation) {
        return mathOperation.operation(a, b);
    }

}
